﻿using System;
using System.Text;
using Abp.Dependency;
using Abp.Extensions;
using Abp.Web.Api.Modeling;
using Abp.Web.Api.ProxyScripting.Generators;

namespace Mt.Site.Web.Scripting
{
    public class AngularProxyScriptGenerator  : IProxyScriptGenerator, ITransientDependency
    {
        /// <summary>
        /// "jquery".
        /// </summary>
        public const string Name = "angularjs";

        public string CreateScript(ApplicationApiDescriptionModel model)
        {
            var script = new StringBuilder();
 
            foreach (var module in model.Modules.Values)
            {
                script.AppendLine();
                AddModuleScript(script, module);
            }

            return script.ToString();
        }

        private static void AddModuleScript(StringBuilder script, ModuleApiDescriptionModel module)
        {
            foreach (var controller in module.Controllers.Values)
            {
                script.AppendLine();
                AddControllerScript(script, module, controller);
            }
        }

        private static void AddControllerScript(StringBuilder script, ModuleApiDescriptionModel module, ControllerApiDescriptionModel controller)
        {
            script.AppendLine("(function (abp, angular) {");
            script.AppendLine("");
            script.AppendLine("    if (!angular) {");
            script.AppendLine("        return;");
            script.AppendLine("    }");
            script.AppendLine("    ");
            script.AppendLine("    var abpModule = angular.module('abp');");
            script.AppendLine("    ");
            script.AppendLine($"    abpModule.factory('abp.services.{module.Name.ToCamelCase()}.{controller.Name.ToCamelCase()}', [");
            script.AppendLine("        '$http', function ($http) {");
            script.AppendLine("            return new function () {");

            foreach (var action in controller.Actions.Values)
            {
                script.AppendLine();
                AddActionScript(script, module, controller, action);
            }

            script.AppendLine("            };");
            script.AppendLine("        }");
            script.AppendLine("    ]);");
            script.AppendLine();

            script.AppendLine();
            script.AppendLine("})((abp || (abp = {})), (angular || undefined));");
            script.AppendLine();
        }

        private static void AddActionScript(StringBuilder script, ModuleApiDescriptionModel module, ControllerApiDescriptionModel controller, ActionApiDescriptionModel action)
        {
            var parameterList = ProxyScriptingJsFuncHelper.GenerateJsFuncParameterList(action, "httpParams");

            script.AppendLine("                this" + ProxyScriptingJsFuncHelper.WrapWithBracketsOrWithDotPrefix(action.Name.ToCamelCase()) + " = function (" + parameterList + ") {");
            script.AppendLine("                    return $http(angular.extend({");
            script.AppendLine("                        url: abp.appPath + '" + ProxyScriptingHelper.GenerateUrlWithParameters(action) + "',");
            script.AppendLine("                        method: '" + action.HttpMethod + "',");

            var para = ProxyScriptingHelper.GenerateBody(action);
            if (para == null) { para = "{}"; }

            if (action.HttpMethod .Equals("GET", StringComparison.OrdinalIgnoreCase))
            {   
                script.AppendLine("                        params: " + para);
            }
            else
            {
                script.AppendLine("                        data: JSON.stringify(" + para + ")");
            }

            script.AppendLine("                    }, httpParams));");
            script.AppendLine("                };");
            script.AppendLine("                ");
        }
    }
}
